/*
** The goal of this program is to find errors in c code.
**
** open the file

** parse the file, spotting errors along the way
** 
** Copyright @ 2020 Joshua Branson <jbranso@dismail.de>
**
** This program is free software; you can redistribute it and/or modify it
** under the terms of the GNU General Public License as published by
** the Free Software Foundation; either version 3 of the License, or (at
** your option) any later version.
**
** It is distributed in the hope that it will be useful, but
** WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

//#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <argp.h>
//#include <sys/mman.h> //mmap
#include <sys/stat.h>
//#include <unistd.h>
#include "structs.h"

char fileName [128];
char * program_invocation_short_name;

const char * argp_program_version = "0.1";
const char * argp_program_bug_address = "jbranso@dismail.de";

static const struct argp_option options [] =
  {
   {"file" , 'f', "FILE", OPTION_ARG_OPTIONAL, "Output the caesar cipher of FILE." },
   { 0 }
  };

//define an argp parse function
error_t argp_parser (int opt, char *arg, struct argp_state *state)
{
  extern char fileName [];
  switch (opt)
    {
      // if this parser function is called on an option that it doesn't recognize, then don't do anything.
    default:
      return ARGP_ERR_UNKNOWN;
    case 'f':
      {
        memcpy (fileName, arg, strlen (arg));
        break;
      }
    }
  return 0;
}

/* a string containing the basic usage of this program. */
struct argp argp =
  {
   options, argp_parser, 0,
   "A simple program implementing a caesar cipher.\nThe default shift is 1."
  };

/* This function will return a buffer whose contents match that of the
   input file. */
FILE * maybe_open_file ()
{
  extern char fileName [];
  extern char * program_invocation_short_name;
  FILE * stream;
  if (strlen (fileName) > 0)
    {
      if ((stream = fopen (fileName, "r")) == NULL)
        {
          fprintf (stderr, "%s: Couldn't open file %s; %s\n",
                   program_invocation_short_name, fileName, strerror (errno));
          exit (EXIT_FAILURE);
        }
      else
        return stream; 
    }
  else
    return stdin;
}

/* This function puts the file in the buffer and returns it. */
char * get_buffer (FILE * stream)
{
  /* size_t page_size = (size_t) sysconf (_SC_PAGESIZE); */
  /* int filedes = shm_open (fileName, O_RDONLY,  S_IRWXU); */
  /* shm_unlink (fileName); */
  /* return mmap (NULL, page_size, PROT_WRITE, MAP_PRIVATE, filedes, 0); */
  extern char fileName[]; 
  char * buf;
  struct stat * file_attrib = malloc (sizeof (struct stat));
  stat (fileName, file_attrib);
  buf = malloc (file_attrib->st_size + 1);
  char c;
  int i;
  for (i = 0; ((c = getc (stream)) != EOF); i++)
    *(buf + i) = c;
  *(buf + i) = '\0';
  return buf;
}

char * remove_backslashes_from_buffer (FILE * stream)
{
  char * c;
  return c;
}

char * remove_comments_from_buffer (char * buf)
{
  char c, d;
  for (int i = 0; ((c =  *(buf + i) ) != '\0'); i++)
    {
      // for now this just removes line comments like this comment.

      //loop forward until you see a '/'
      if (c == '/')
        {
          if ((d = ( *(buf + i + 1))) == '/') 
            {
              //loop forward until you see a '\n'.
              i += 2;
              while (*(buf + i) != '\n')
                i++;
            }
          else
            {
              // if the next char is not a '\', then put the
              // "\\[a-zA-Z0-9]" in the buffer.  eg: if you find a "'\a'"
              // then just put it in the buffer.
              i++;
              continue;
            }
        }
      else 
        {
          *(buf + i) = c; 
        }
    }
}

struct string_t * parse_buffer_into_string_ts (char * c)
{
  struct string_t * strings;
  strings = malloc (sizeof (struct string_t));
  return strings; 
}

int main (int argc, char **argv)
{
  argp_parse (&argp, argc, argv, 0, 0, 0);
  FILE * stream = maybe_open_file ();
  char * buf = get_buffer (stream);
  printf ("%s\n", buf);
  remove_comments_from_buffer (buf);
  printf ("%s\n", buf);
  return 0;
}
